home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / lib / addr / ap_normali.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-28  |  15.6 KB  |  600 lines

  1. #include "util.h"
  2. #include "conf.h"
  3. #include "ll_log.h"
  4. #include "ch.h"
  5. #include "ap.h"
  6. #include "ap_norm.h"
  7. #include "dm.h"
  8.  
  9. /*  Normalize a parse tree, to fill-in host references, etc.
  10.  *
  11.  *  Returns:    0  if ok
  12.  *              -1 if error
  13.  */
  14.  
  15. extern LLog *logptr;
  16. extern struct ap_hstab *ap_exhstab;     /* translation table */
  17. extern char *locname;
  18. extern char *locdomain;
  19. extern char *locfullname;
  20. extern char *locfullmachine;
  21.  
  22. extern char *strdup ();
  23. extern char *multcat ();
  24. Domain *dm_v2route();
  25.  
  26. LOCFUN logtree(), ap_ptinit();
  27.  
  28. /* */
  29.  
  30. AP_ptr
  31.     ap_normalize (dflhost, dfldomain, thetree, exorchan)
  32.     char *dflhost,             /* string to append, as host name */
  33.      *dfldomain;           /* string to append, as domain name */
  34.     AP_ptr thetree;             /* the parse tree */
  35.     Chan  *exorchan;            /* The channel to exorcise with respect to */
  36. {
  37.     struct ap_node  basenode;     /* first node in routing chain          */
  38.     AP_ptr r822prefptr,
  39.        perptr,
  40.        mbxprefptr,
  41.        dmprefptr,
  42.        lstcmntprefptr,
  43.        lastptr,
  44.        grpptr,
  45.        ap;
  46.     struct ap_hstab  *tabp;
  47.     char    official[128];
  48.     char *save;
  49.  
  50. #ifdef DEBUG
  51.     ll_log (logptr, LLOGBTR, "ap_normalize (%s, %s, ..., %s)",
  52.         seenull(dflhost), seenull(dfldomain),
  53.         exorchan ? seenull(exorchan->ch_show) : "no-chan");
  54.     logtree (thetree, "normalize input");
  55. #endif
  56.  
  57.     ap_ninit (&basenode);
  58.     ap_sqinsert (&basenode, APP_ETC, thetree);
  59.                 /* make sure that 'pref' ptrs are easy  */
  60.     ap_ptinit (&basenode, &perptr, &r822prefptr, &mbxprefptr, &dmprefptr,
  61.                 &lstcmntprefptr, &lastptr, &grpptr);
  62.                 /* set some pointers */
  63.  
  64.  
  65.             /* SEK - lts try replacing this section        */
  66.             /* It may have marginal use                    */
  67.     if (perptr == (AP_ptr) 0 && grpptr == (AP_ptr) 0
  68.     && lstcmntprefptr != (AP_ptr) 0)
  69.     {                   /* no person name or group, so use last comment */
  70. #ifdef DEBUG
  71.         ll_log (logptr, LLOGFTR, "ap_normalize: comment -> person name");
  72. #endif
  73.  
  74.     ap_insert (&basenode, APP_ETC,
  75.             ap_new (APV_NPER,
  76.                 lstcmntprefptr -> ap_chain -> ap_obvalue));
  77.  
  78.     if (mbxprefptr == &basenode)  /* first node was local-part */
  79.         mbxprefptr = basenode.ap_chain;
  80.  
  81.     ap_append (lastptr, APV_EPER, (char *) 0);
  82. #ifdef DEBUG
  83.     logtree (basenode.ap_chain, "ap_normalize: comment result");
  84. #endif
  85.     }
  86.  
  87.     /*
  88.      *  Remember "list: ;"...   -DPK-
  89.      */
  90.     if (mbxprefptr == (AP_ptr) 0) {
  91. #ifdef DEBUG
  92.     ll_log (logptr, LLOGFTR, "ap_normalize: No mailbox!?!");
  93. #endif
  94.     return (basenode.ap_chain);
  95.     }
  96.  
  97.                 /* Normalize all refs in source route   */
  98.     if (r822prefptr != (AP_ptr) 0)
  99.     {
  100.     ap = r822prefptr;
  101.     FOREVER
  102.     {
  103.         switch (ap -> ap_ptrtype) {
  104.         case APP_NIL:
  105.         case APP_NXT:
  106.             break;
  107.         case  APP_ETC:
  108.             ap = ap -> ap_chain;
  109.             if(ap == (AP_ptr)0)
  110.             break;
  111.             switch (ap -> ap_obtype) {
  112.             case APV_DOMN:
  113.                if(ap_dmnormalize (ap, exorchan) == MAYBE)
  114.                 return( (AP_ptr)MAYBE);
  115.             case APV_DLIT:
  116.             case APV_CMNT:
  117.             continue;
  118.             }
  119.         }
  120.         break;
  121.     }
  122.     }
  123.  
  124. #ifndef JNTMAIL
  125.     /*
  126.      *  SEK if JNT mail, % is treated as lexically equivalent
  127.      *  to @, and CSNET style routes ignored.  Might accept
  128.      *  CSNET routes if someone wants this...
  129.      */
  130.     if (dmprefptr == (AP_ptr) 0)
  131.     {                           /* no domain, so add default and leave */
  132. #ifdef DEBUG
  133.     ll_log (logptr, LLOGFTR, "ap_normalize: no domain");
  134. #endif
  135.     ap_locnormalize (&basenode, &r822prefptr, &mbxprefptr, &dmprefptr);
  136. #ifdef DEBUG
  137.     logtree (basenode.ap_chain, "ap_normalize: locnorm result");
  138. #endif
  139.     }
  140. #endif /* not JNTMAIL */
  141.  
  142.     if (dmprefptr != (AP_ptr) 0) {
  143.     switch(ap_dmnormalize (dmprefptr -> ap_chain, exorchan)) {
  144.     case MAYBE:
  145.         return ( (AP_ptr)MAYBE);
  146.     case OK:;
  147. #ifdef DEBUG
  148.         ll_log (logptr, LLOGFTR, "ap_normalize: Local reference");
  149. #endif
  150. #ifndef JNTMAIL
  151.         ap_locnormalize (&basenode, &r822prefptr, &mbxprefptr, &dmprefptr);
  152. #ifdef DEBUG
  153.     logtree (basenode.ap_chain, "ap_normalize: locnorm(2) result");
  154. #endif
  155. #endif /* not JNTMAIL */
  156.     }
  157.     }
  158.  
  159.  
  160.     if (dmprefptr == (AP_ptr) 0 && r822prefptr == (AP_ptr) 0)
  161.     {                           /* no host references anywhere */
  162. #ifdef DEBUG
  163.     ll_log (logptr, LLOGFTR, "ap_normalize: mbx = %o, mbx->typ = %o, mbx->ch = %o",
  164.         mbxprefptr, mbxprefptr->ap_obtype, mbxprefptr->ap_chain);
  165.     if (mbxprefptr != (AP_ptr) 0)
  166.         ll_log (logptr, LLOGFTR, "mbx->ch->ty = %o", mbxprefptr->ap_chain->ap_obtype);
  167. #endif
  168.     if (mbxprefptr == (AP_ptr) 0
  169.        || mbxprefptr -> ap_chain -> ap_obtype == APV_NGRP
  170.        || mbxprefptr -> ap_chain -> ap_obtype == APV_GRUP)  /* Yuck. */
  171.         return (basenode.ap_chain);
  172.  
  173.     if (!isstr(dflhost))
  174.     {
  175.         strcpy(official, locfullname);
  176.         ap_append (mbxprefptr -> ap_chain, APV_DOMN, official);
  177. #ifdef DEBUG
  178.         ll_log (logptr, LLOGFTR, "appending %s domain (local)",
  179.             official);
  180. #endif
  181.     }
  182.     else
  183.     {
  184.         if (!isstr(dfldomain))
  185.         (void) strcpy (official, dflhost);
  186.         else
  187.         sprintf (official, "%s.%s", dflhost, dfldomain);
  188.         ap_append (mbxprefptr -> ap_chain, APV_DOMN, official);
  189. #ifdef DEBUG
  190.         ll_log (logptr, LLOGFTR, "appending %s domain",
  191.             official);
  192. #endif
  193.         if(ap_dmnormalize (mbxprefptr -> ap_chain -> ap_chain,
  194.                             exorchan) == MAYBE)
  195.         return( (AP_ptr)MAYBE);
  196.     }
  197.     return (basenode.ap_chain);
  198.     }
  199.  
  200. #ifdef DEBUG
  201.     ll_log (logptr, LLOGFTR, "exorcise special host refs");
  202. #endif
  203.                 /* SEK change the dreaded exorcising */
  204.                 /* so as only to apply to the host   */
  205.                 /* directly connected to.  It is     */
  206.                 /* absurd to do this to the middle of*/
  207.                 /* a source route                    */
  208.     if (r822prefptr != (AP_ptr) 0)
  209.     ap = r822prefptr -> ap_chain;
  210.     else
  211.     ap = dmprefptr -> ap_chain;
  212.  
  213.     for (tabp = ap_exhstab; tabp -> name != (char *) 0; tabp++)
  214.     if (lexequ (tabp -> name, ap -> ap_obvalue))
  215.     {             /* Yes, perform holy rites */
  216. #ifdef DEBUG
  217.         ll_log (logptr, LLOGFTR, "exorcising: %s -> %%%s@%s",
  218.             ap -> ap_obvalue, tabp -> dot, tabp -> at);
  219. #endif
  220.         if (isstr (tabp -> dot)) {
  221.         free (ap -> ap_obvalue);
  222.         ap -> ap_obvalue = strdup (tabp -> at);
  223.         save = mbxprefptr -> ap_chain -> ap_obvalue;
  224.         mbxprefptr -> ap_chain -> ap_obvalue = multcat (
  225.            mbxprefptr -> ap_chain -> ap_obvalue, "%", tabp -> dot, (char *)0);
  226.         } else {
  227.         save = ap -> ap_obvalue;
  228.         ap -> ap_obvalue = strdup (tabp -> at);
  229.         }
  230.         free (save);
  231.         return (basenode.ap_chain);
  232.     }
  233.  
  234.     /*
  235.      *  We do not have a specific exorcising rule.  See if the
  236.      *  host is known to this channel, and if not, exocise it anyway.
  237.      *
  238.      *  (I think this will work, closer examination welcome.  -DPK-)
  239.      *
  240.      *   SEK -
  241.      *          only play this game if ch_known is specified.
  242.      *           to allow it to be turned off
  243.      *
  244.      *          assume that the table is a channel table form
  245.      *          and thus we need the first host name
  246.      */
  247.     if (exorchan != NULL && exorchan -> ch_known != NULL) {
  248.     Dmn_route route;
  249.     char dm_buf[LINESIZE];
  250.     Domain *lrval;
  251.     int irval;
  252.  
  253.     lrval = dm_v2route (ap -> ap_obvalue, dm_buf, &route);
  254.     if(lrval == (Domain *)MAYBE)
  255.         return( (AP_ptr)MAYBE);
  256.     else if(lrval == (Domain *)NOTOK) {
  257.         ll_log (logptr, LLOGTMP, "failure to reconvert domain (%s)",
  258.             ap-> ap_obvalue);
  259.         return (basenode.ap_chain);
  260.     }
  261.                 /* SEK this might need beefing up to cope    */
  262.                 /* with unknown subdomains              */
  263.  
  264.     irval = tb_k2val(exorchan->ch_known, TRUE, route.dm_argv[0], official);
  265.     if(irval == MAYBE)
  266.         return( (AP_ptr)MAYBE);
  267.     else if(irval == NOTOK) {
  268.         if (r822prefptr == (AP_ptr) 0) {
  269. #ifdef DEBUG
  270.         ll_log (logptr, LLOGFTR, "exorcising: %s -> %%%s@%s",
  271.             ap -> ap_obvalue,
  272.             route.dm_argv[0], exorchan -> ch_lname);
  273. #endif
  274.  
  275.         save = mbxprefptr -> ap_chain -> ap_obvalue;
  276.         mbxprefptr -> ap_chain -> ap_obvalue = multcat (
  277.             mbxprefptr->ap_chain->ap_obvalue, "%",
  278.             route.dm_argv[0], (char *)0);
  279.         free (save);
  280.         free (dmprefptr -> ap_chain -> ap_obvalue);
  281.         dmprefptr -> ap_chain -> ap_obvalue =
  282.             multcat (exorchan->ch_lname,
  283.                     ".", exorchan->ch_ldomain, (char *)0);
  284.        } else {
  285. #ifdef DEBUG
  286.         ll_log (logptr, LLOGFTR, "adding exorcise component to route");
  287. #endif
  288.                   /* SEK note ap points to r822prefptr - chain */
  289.         ap_sqinsert (ap, APP_ETC, ap_new (ap -> ap_obtype, ap -> ap_obvalue));
  290.         free (ap -> ap_obvalue);
  291.         ap -> ap_obvalue = multcat (exorchan->ch_lname,
  292.                         ".", exorchan->ch_ldomain, (char *)0);
  293.        }
  294.         }
  295.     }
  296.     return (basenode.ap_chain);
  297. }
  298. /* */
  299.  
  300. LOCFUN
  301.     ap_ptinit (baseprefptr, perptr, r822prefptr, mbxprefptr, dmprefptr,
  302.                 lstcmntprefptr, lastptr, grpptr)
  303.     AP_ptr baseprefptr;
  304.     AP_ptr *perptr,
  305.        *r822prefptr,
  306.        *mbxprefptr,
  307.        *dmprefptr,
  308.        *lstcmntprefptr,
  309.        *lastptr,
  310.        *grpptr;
  311. {
  312.     AP_ptr ap;
  313.  
  314. #ifdef DEBUG
  315.     ll_log (logptr, LLOGFTR, "ap_ptinit (%s, %d)", 
  316.         seenull(baseprefptr->ap_obvalue), baseprefptr->ap_obtype);
  317. #endif
  318.  
  319.     *perptr =
  320.     *r822prefptr =
  321.     *mbxprefptr =
  322.     *dmprefptr =
  323.     *lstcmntprefptr =
  324.     *lastptr =
  325.     *grpptr = (AP_ptr) 0;
  326.  
  327.                 /* SEK need switch here to catch */
  328.                 /* leadin mbox or domn           */
  329.      switch (baseprefptr -> ap_chain -> ap_obtype)
  330.      {
  331.     case APV_MBOX:
  332.         *mbxprefptr = baseprefptr;
  333.         break;
  334.     case APV_DLIT:
  335.     case APV_DOMN:
  336.         *r822prefptr = baseprefptr;
  337.      }
  338.  
  339.  
  340.     for (ap = baseprefptr -> ap_chain; ap -> ap_obtype != APV_NIL;
  341.         ap = ap -> ap_chain)
  342.     {
  343.     *lastptr = ap;
  344. #ifdef DEBUG
  345.     ll_log (logptr, LLOGFTR, "ap_ptinit: val '%s'", seenull(ap -> ap_obvalue));
  346. #endif
  347.     switch (ap -> ap_obtype)
  348.     {
  349.         case APV_NPER:
  350. #ifdef DEBUG
  351.         ll_log (logptr, LLOGFTR, "ap_ptinit: perptr");
  352. #endif
  353.         *perptr = ap;
  354.         break;
  355.  
  356.         case APV_NGRP:
  357. #ifdef DEBUG
  358.         ll_log (logptr, LLOGFTR, "ap_ptinit: grpptr");
  359. #endif
  360.         *grpptr = ap;
  361.         break;
  362.     }
  363.  
  364.     if (ap -> ap_ptrtype == APP_NXT)
  365.         break;
  366.     if (ap -> ap_ptrtype == APP_NIL)
  367.         break;
  368.     if (ap -> ap_chain == (AP_ptr) 0)
  369.         break;
  370.  
  371.     switch (ap -> ap_chain -> ap_obtype)
  372.     {
  373.         case APV_CMNT:
  374. #ifdef DEBUG
  375.         ll_log (logptr, LLOGFTR, "ap_ptinit: gotcmnt");
  376. #endif
  377.         *lstcmntprefptr = ap;
  378.         break;                          /** DPK@BRL **/
  379.  
  380.         case APV_WORD:                      /** DPK@BRL **/
  381. #ifdef DEBUG
  382.         ll_log (logptr, LLOGFTR, "ap_ptinit: gotword");
  383. #endif
  384.         if (*mbxprefptr != (AP_ptr) 0)
  385.             break;
  386.  
  387.         case APV_MBOX:
  388. #ifdef DEBUG
  389.         ll_log (logptr, LLOGFTR, "ap_ptinit: gotmbxpref");
  390. #endif
  391.         *mbxprefptr = ap;    /* one before the mbox                */
  392.         break;
  393.  
  394.         case APV_DLIT:
  395.         case APV_DOMN:
  396.         if (*r822prefptr == (AP_ptr) 0 && *mbxprefptr == (AP_ptr) 0) {
  397. #ifdef DEBUG
  398.             ll_log (logptr, LLOGFTR, "ap_ptinit: got r822prefptr");
  399. #endif
  400.             *r822prefptr = ap;
  401.         } else
  402.         if ((*dmprefptr == (AP_ptr) 0) && (*mbxprefptr != (AP_ptr) 0)) {
  403.                     /* SEK need mailbox befor domain */
  404. #ifdef DEBUG
  405.             ll_log (logptr, LLOGFTR, "ap_ptinit: gotdmprefptr");
  406. #endif
  407.             *dmprefptr = ap;
  408.         }
  409.         break;
  410.     }
  411.     }
  412. #ifdef DEBUG
  413.     if (*lastptr == (AP_ptr) 0)
  414.     ll_log (logptr, LLOGFTR, "ap_ptinit: no lastptr");
  415.     else
  416.     ll_log (logptr, LLOGFTR, "ap_ptinit: lastptr '%s'", 
  417.             seenull((*lastptr) -> ap_obvalue));
  418. #endif
  419.  
  420. }
  421. /* */
  422. #ifndef    JNTMAIL
  423.  
  424. ap_locnormalize (obaseptr, or822prefptr, ombxprefptr, odmprefptr)
  425.     AP_ptr obaseptr,
  426.        *or822prefptr,
  427.        *ombxprefptr,
  428.        *odmprefptr;
  429. {                           /* tear local-part apart            */
  430.     struct ap_node basenode;
  431.     AP_ptr curptr;
  432.     AP_ptr r822prefptr,
  433.        perptr,
  434.        mbxprefptr,
  435.        dmprefptr,
  436.        lstcmntprefptr,
  437.        lastptr,
  438.        grpptr;
  439.     char *cptr;
  440.  
  441. #ifdef DEBUG
  442.     ll_log (logptr, LLOGBTR, "ap_locnormalize ()");
  443. #endif
  444.                 /* SEK need fixex here to normalize any new */
  445.                 /* domain references                        */
  446.  
  447. #ifdef DONE_IN_SUBMIT
  448.     if( ! ((*ombxprefptr) -> ap_obtype == APV_DTYP &&   /* protect files */
  449.       lexequ((*ombxprefptr) -> ap_obvalue, "include")))
  450.     for (cptr = (*ombxprefptr) -> ap_chain -> ap_obvalue;
  451.          *cptr != '\0'; cptr++)
  452.         if (*cptr == '.' || *cptr == '%')
  453.         *cptr = '@';
  454. #endif
  455.  
  456. #ifdef DEBUG
  457.     ll_log (logptr, LLOGBTR, "parsing '%s'", (*ombxprefptr) -> ap_chain -> ap_obvalue);
  458. #endif
  459.  
  460.     ap_ninit (&basenode);
  461.     ap_sqinsert (&basenode, APP_ETC,
  462.             ap_s2tree ((*ombxprefptr) -> ap_chain -> ap_obvalue));
  463. #ifdef DEBUG
  464.     logtree (obaseptr -> ap_chain, "parse result");
  465. #endif
  466.     ap_ptinit (&basenode, &perptr, &r822prefptr, &mbxprefptr, &dmprefptr,
  467.                 &lstcmntprefptr, &lastptr, &grpptr);
  468.     if (dmprefptr != (AP_ptr) 0)    /* actually have some stuff */
  469.     {
  470.     free ((*ombxprefptr) -> ap_chain -> ap_obvalue);
  471.     (*ombxprefptr) -> ap_chain -> ap_obvalue =
  472.             strdup (mbxprefptr -> ap_chain -> ap_obvalue);
  473.                 /* replace old reference */
  474. #ifdef DEBUG
  475.     ll_log (logptr, LLOGFTR,
  476.         "newlocal '%s'", (*ombxprefptr) -> ap_chain -> ap_obvalue);
  477. #endif
  478.     if (r822prefptr != (AP_ptr) 0 || *odmprefptr != (AP_ptr) 0)
  479.         if (*or822prefptr == (AP_ptr) 0) {
  480. #ifdef DEBUG
  481.         logtree (obaseptr -> ap_chain, "odm move result");
  482. #endif
  483.         *or822prefptr = obaseptr;
  484.         }                   /* initialize route pointer */
  485.  
  486.     if (*odmprefptr == (AP_ptr) 0)
  487.         *odmprefptr = mbxprefptr -> ap_chain;
  488.     else                    /* get rid of old domain reference */
  489.     {
  490.         ap_move (*or822prefptr, *odmprefptr);
  491. #ifdef DEBUG
  492.         logtree (obaseptr -> ap_chain, "odm move result");
  493. #endif
  494.     }
  495.  
  496.     if (r822prefptr != (AP_ptr) 0)
  497.     {                       /* put new chain at end of old          */
  498. #ifdef DEBUG
  499.         ll_log (logptr, LLOGFTR, "adding new routing to end info");
  500. #endif
  501.         for (curptr = *or822prefptr;
  502.             curptr -> ap_chain -> ap_obtype == APV_DOMN ||
  503.                 curptr -> ap_chain -> ap_obtype == APV_DLIT ||
  504.                 curptr -> ap_chain -> ap_obtype == APV_CMNT;
  505.             curptr = curptr -> ap_chain);
  506.         ap_sqmove (curptr, r822prefptr, APV_DOMN);
  507. #ifdef DEBUG
  508.         logtree (obaseptr -> ap_chain, "routing move result");
  509. #endif
  510.     }
  511.  
  512.     ap_move (*odmprefptr, dmprefptr);
  513. #ifdef DEBUG
  514.     logtree (obaseptr -> ap_chain, "dm move result");
  515. #endif
  516.     }
  517. }
  518. #endif /* not    JNTMAIL */
  519.  
  520. /* */
  521.  
  522. ap_dmnormalize (dmptr, thechan)
  523. register AP_ptr dmptr;
  524. Chan *thechan;
  525. {
  526.     Dmn_route dmnroute;
  527.     char official [LINESIZE];
  528.     char buf[LINESIZE];
  529.     Domain *domain;
  530.  
  531. #ifdef DEBUG
  532.     ll_log (logptr, LLOGBTR, "ap_dmnormalize (%s, %s)",
  533.         seenull(dmptr->ap_obvalue),
  534.         thechan ? seenull(thechan->ch_show) : "no-chan");
  535. #endif
  536.  
  537.     domain = dm_v2route (dmptr -> ap_obvalue, official, &dmnroute);
  538.     switch ((int)domain) {
  539.                     /* do we know this reference? */
  540.     case NOTOK:            /* unknown host */
  541. #ifdef DEBUG
  542.         ll_log (logptr, LLOGBTR, "unknown domain (ap_dmnormalize): '%s'",
  543.                 dmptr -> ap_obvalue);
  544. #endif
  545.         switch ((int)ch_nm2struct (dmptr -> ap_obvalue))
  546.         {                   /* explicit channel routing? */
  547.         default:        /* it IS a channel name */
  548.             return (OK);
  549.                 /* return an analyse local part        */
  550.                 /* leave channel ref in address        */
  551.         case NOTOK:
  552.            ll_log (logptr, LLOGFST,
  553.                 "nonexistent dom/host (ap_dmnormalize): '%s'",
  554.                 seenull(dmptr -> ap_obvalue));
  555.             return (NOTOK);
  556.         }
  557.     case MAYBE:
  558.         return(MAYBE);
  559.     default:
  560.         strcpy (buf, locfullname);
  561.                 /* SEK might be better to get dm_v2route */
  562.                 /* to do this                            */
  563.         if (lexequ (official, buf) && (thechan != NULL)) {
  564.         if (isstr(thechan -> ch_ldomain))
  565.             sprintf (official, "%s.%s", thechan -> ch_lname,
  566.                 thechan -> ch_ldomain);
  567.         else
  568.             sprintf (official, "%s", thechan -> ch_lname);
  569.         }
  570.     }
  571.  
  572. #ifdef DEBUG
  573.     ll_log (logptr, LLOGFTR, "ap_dmnormalize: Route = '%s', Official name = '%s'",
  574.         dmnroute.dm_buf, official);
  575. #endif
  576.     free (dmptr -> ap_obvalue);
  577.     dmptr -> ap_obvalue = strdup (official);
  578.     return (7);                 /* anything other than OK /  NOTOK */
  579. }
  580.  
  581. /* */
  582.  
  583. #ifdef DEBUG
  584. LOCFUN
  585.      logtree(thetree, text)  /* if FTR, convert tree to string & log */
  586.  
  587. AP_ptr thetree;
  588. char *text;
  589. {
  590.     if (logptr->ll_level == LLOGFTR) {
  591.  
  592.     char *cptr;
  593.  
  594.     ap_t2s (thetree, &cptr);
  595.     ll_log (logptr, LLOGFTR, "%s:  %s", text, cptr);
  596.     free (cptr);
  597.     }
  598. }
  599. #endif /* DEBUG */
  600.